using System;
using System.Xml;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Drawing;

namespace CodeEdit
{
	/// <summary>
	/// Summary description for EditorConfiguration.
	/// </summary>
	public class EditorConfiguration
	{
		// Path to the Config.xml file.
		private string path = "";
		private Hashtable WriteHash;
		public static string keywordFile;
		public static string ConfigPath;

		public static Hashtable ConfigVars;
		public static Hashtable keywords;

		public static bool NoConfigFile;
		public static bool BadConfigFile;
		public static bool NoKeywordFile;
		public static bool BadKeywordFile;

		public static bool doHighlight=false;
		public static bool doComment=false;
		public static bool canHighlight=false;
		public static bool canComment=false;
		public static Color commentColor, foreColor, backColor;

		private static ColorConverter mapToColor = new ColorConverter();

		static EditorConfiguration() {
			try {
				ConfigPath = "Config.xml";
				// Find the location of the keyword file and store it in a variable.
				EditorConfiguration info = new EditorConfiguration(ConfigPath);
				keywordFile = info.GetInfo("KeyWordFile");

				// Store all variables of the configuration file into the ConfigHash.
				ConfigVars = EditorConfiguration.ReadConfigFile(ConfigPath);

				// Read in the Keywords and their Colors (for Syntax Highlighting).
				keywords = EditorConfiguration.ReadXmlToHash(keywordFile);

				EditorConfiguration.LoadKeywords(keywords, keywordFile);
				doHighlight = (string)ConfigVars["synHigh"]=="True";
				doComment = (string)ConfigVars["comments"]=="True";
				canHighlight = false;
				canComment = false;
				doHighlight = false;
				doComment = false;

				commentColor = (Color)mapToColor.ConvertFromString((string)info.GetInfo("CommentColor"));
				backColor = (Color)mapToColor.ConvertFromString((string)info.GetInfo("CurrentBg").ToString());
				foreColor = (Color)mapToColor.ConvertFromString((string)info.GetInfo("CurrentFont").ToString());
			} catch (Exception ex) {
				ex =ex;
			}
		}


		// Constructor for pulling XML information.
		public EditorConfiguration(string path)
		{
			this.path = path;
		}

		// Constructor for pulling XML information.
		public EditorConfiguration(string path, Hashtable hash)
		{
			this.WriteHash = hash;
			this.path = path;
		}

		// Pull out a piece of information from the Config.xml file
		// based on a tag name.
		public string GetInfo(string infoItem)
		{
			string ConfigFile = this.path;
			string result = "";

			if (!File.Exists(ConfigFile))
			{
				return "N/A";
			}

			XmlTextReader configReader = null;
			configReader = new XmlTextReader(ConfigFile);

			// Read in the data from the given XML Tag.
			while (configReader.Read())
			{
				if (configReader.NodeType == XmlNodeType.Element)
				{
					if (configReader.LocalName.Equals(infoItem))
					{
						result = configReader.ReadString();
						configReader.Close();
						return result;
					}
				}
			}
			configReader.Close();
			return result;
		}

		// Saves Configuration changes.
		public void SaveInfo()
		{
			XmlTextWriter configWriter = null;
			configWriter = new XmlTextWriter(this.path, null);

			try
			{
				configWriter.Formatting = Formatting.Indented;
				configWriter.Indentation= 6;
				configWriter.Namespaces = false;

				configWriter.WriteStartDocument();

				configWriter.WriteStartElement("", "config", "");

				configWriter.WriteStartElement("", "KeyWordFile", "");
				configWriter.WriteString(this.WriteHash["keywords"].ToString());
				configWriter.WriteEndElement();

				configWriter.WriteStartElement("", "SyntaxHighlighting", "");
				configWriter.WriteString(this.WriteHash["synHigh"].ToString());
				configWriter.WriteEndElement();

				configWriter.WriteStartElement("", "Commenting", "");
				configWriter.WriteString(this.WriteHash["comments"].ToString());
				configWriter.WriteEndElement();

				configWriter.WriteStartElement("", "DefaultBg", "");
				configWriter.WriteString(this.WriteHash["defBg"].ToString());
				configWriter.WriteEndElement();

				configWriter.WriteStartElement("", "DefaultFont", "");
				configWriter.WriteString(this.WriteHash["defFont"].ToString());
				configWriter.WriteEndElement();

				configWriter.WriteStartElement("", "CurrentBg", "");
				configWriter.WriteString(this.WriteHash["currBg"].ToString());
				configWriter.WriteEndElement();

				configWriter.WriteStartElement("", "CurrentFont", "");
				configWriter.WriteString(this.WriteHash["currFont"].ToString());
				configWriter.WriteEndElement();

				configWriter.WriteStartElement("", "CommentColor", "");
				configWriter.WriteString(this.WriteHash["cmntColor"].ToString());
				configWriter.WriteEndElement();

				configWriter.WriteEndElement();
				configWriter.Flush();
			}
			catch(Exception e)
			{
				MessageBox.Show("Error: " + e.Message + "\n" + e.Source + "\n" + e.TargetSite);
			}
			configWriter.Close();
		}

		/*
		  Reads the Configuration File to determine global settings
		  Currently supports:
			KeywordFile -- Location of keyword file.
			SyntaxHighlighting -- Whether or not user wants Syntax Highlighting enabled.
			Commenting -- Whether or not user wants Commenting features enabled.
			Default Background Color -- Default background color --> White (not editable).
			Default Font Color -- Default font color --> Black (not editable).
			Current Background Color -- Sets the GUI's background color to the user's choice.
			Current Font Color -- Sets to Font color to the user's choice.
		*/
		public static Hashtable ReadConfigFile(string configFile) {
			Hashtable configHash = new Hashtable();
			XmlTextReader configReader = null;

			FileInfo fi = new FileInfo(configFile);
			
			// Make sure the Configuration file exists.
			if (fi.Exists == false) {
				NoConfigFile = true;
				//MessageBox.Show(
				//	"No Configuration file exists for the GUI.\n" + 
				//	"Either it has been removed or it is stored in a separate directory");
				return configHash;
			}
			configReader = new XmlTextReader(configFile);
			string keywords = "";
			string synHigh = "";
			string comments = "";
			string defBg = "";
			string defFont = "";
			string currBg = "";
			string currFont = "";
			string cmntColor = "";

			// Loop through the Configuration file and set the global Config variables.
			try {
				while (configReader.Read()) {
					if (configReader.NodeType == XmlNodeType.Element) {
						// Get current Keyword File.
						if (configReader.LocalName.Equals("KeyWordFile")) {
							keywords = configReader.ReadString();
							configHash.Add("keywords", keywords.ToString());
						}

						// Determine if Syntax Highlighting is enabled.
						if (configReader.LocalName.Equals("SyntaxHighlighting")) {
							synHigh = configReader.ReadString();
							configHash.Add("synHigh", synHigh.ToString());
						}

						// Determine if Commenting features are enabled.
						if (configReader.LocalName.Equals("Commenting")) {
							comments = configReader.ReadString();
							configHash.Add("comments", comments.ToString());
						}

						// Read in the default editor background color.
						if (configReader.LocalName.Equals("DefaultBg")) {
							defBg = configReader.ReadString();
							configHash.Add("defBg", defBg.ToString());
						}

						// Read in the default font color.
						if (configReader.LocalName.Equals("DefaultFont")) {
							defFont = configReader.ReadString();
							configHash.Add("defFont", defFont.ToString());
						}

						// Read in the default editor background color.
						if (configReader.LocalName.Equals("CurrentBg")) {
							currBg = configReader.ReadString();
							configHash.Add("currBg", currBg.ToString());
						}

						// Read in the default font color.
						if (configReader.LocalName.Equals("CurrentFont")) {
							currFont = configReader.ReadString();
							configHash.Add("currFont", currFont.ToString());
						}

						// Read in the default font color.
						if (configReader.LocalName.Equals("CommentColor")) {
							cmntColor = configReader.ReadString();
							configHash.Add("cmntColor", cmntColor.ToString());
						}
					}
				}
			}
			catch(Exception ex) {
				ex = ex;  // suppress compiler warning that ex isn't used
				// Set the BadConfigFile error to true.  This will prevent errors with the
				// SyntaxHighlighting and Commenting.
				BadConfigFile = true;
				//MessageBox.Show("The current configuration file is corrupt.\nPlease change or replace it");
			}

			// Make sure the Configuration file is not corrupt.
			if ((cmntColor == "") || 
				(currFont == "") || 
				(currBg == "") || 
				(defFont == "") || 
				(defBg == "") ||
				(comments == "") ||
				(synHigh == "") ||
				(keywords == "")) {
				// Set the BadConfigFile error to true.  This will prevent errors with the
				// SyntaxHighlighting and Commenting.
				BadConfigFile = true;
				//MessageBox.Show("The current configuration file is corrupt\nPlease change or replace it");
			}
			configReader.Close();

			return configHash;

		}

		// Reads keywords from XML file into the keywordsHash table.
		public static Hashtable ReadXmlToHash(string filename) {
			Hashtable KeyHash = new Hashtable();
			XmlTextReader keywordReader = null;
			keywordReader = new XmlTextReader(filename);
			string word = "";
			string color = "";

			// Make sure the Keyword file exists.
			if (!File.Exists(filename)) {
				NoKeywordFile = true;
				//MessageBox.Show("The Keyword file is missing.  Please select a new keyword file in the Options Dialog Box");
				return KeyHash;
			}

			// Loop through the file and store the keyword --> color pairs in the KeyHash.
			try {
				while (keywordReader.Read()) {

					if (keywordReader.NodeType == XmlNodeType.Element) {
						if (keywordReader.LocalName.Equals("keywords")) {
							continue;
						}
					
						// Read the word you will color.
						if (keywordReader.LocalName.Equals("word")) {
							word = keywordReader.ReadString();
						}

						// Read the color you will color the current word with.
						if (keywordReader.LocalName.Equals("color")) {
							color = keywordReader.ReadString();
						}
					
						// If the word and color are set to values, add them
						// to the KeyHash and reset their values to "".
						if ((word != "") && (color != "")) {
							// Add the keyword --> color combination to the KeyHash
							KeyHash.Add(word, color);
							word = "";
							color = "";
						}
					}
				}
			}
				// If an error occurred, set the BadKeywordFile variable to true.
			catch (Exception ex) {
				ex = ex;  // suppress compiler warning that ex isn't used
				BadKeywordFile = true;
				//MessageBox.Show("Keyword File is corrupt.\nPlease change or replace it");
			}

			// Close the file.
			keywordReader.Close();

			return KeyHash;
		}

		//Syntax Highlighting Functions - Rachel, Jeff, and Mazen

		//Opens the path pointed to by the keyword path variable 
		//and loads all of the keywords from that file into the 
		//global hash KeyWords
		private static void LoadKeywords(Hashtable keywords, String path) {
			if (!File.Exists(path)) {
				//MessageBox.Show("Could not find keyword file: will not perform syntax highlighting \n");
			}
			else {
				using (StreamReader kwds = new StreamReader(path)) {
					/*if (kwds < 0) {
						MessageBox.Show("Error opening file: " + path + 
							"\n Will not perform syntax highlighting. Please make sure you have the appropriate files installed to receive syntax highlighting features.");
					} 
					else { */
					string line;
					while ((line = kwds.ReadLine()) != null) {
						char[] delims = new char[2];
						delims[0] = '\t';
						delims[1] = ' ';
						string[] into_hash = line.Split(delims);
						//check to make sure valid values are being loaded
						//Valid_Value?(values, path)
						//keywords.Add(into_hash[0], into_hash[1]);
					}
					//}
					kwds.Close();
				}
			}
		}
	}
}
